package cn.dvptech.remotemate.other

import android.media.MediaCodec
import android.media.MediaCodecInfo
import android.media.MediaFormat
import android.view.Surface
import kotlinx.coroutines.*
import java.nio.ByteBuffer
import kotlinx.coroutines.channels.Channel
/**
 *    author  : ulongx
 *    website : www.dvptech.cn
 *    date    : 2024/7/9
 *    desc    :
 */

class VideoDecoder(private val surface: Surface) {

    private var mediaCodec: MediaCodec? = null
    private var isDecoding = false
    private var frameCount = 0L
    private var startTimeNanos = 0L
    private val decodeScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
    private val frameDataQueue = Channel<Pair<ByteBuffer, Long>>(Channel.UNLIMITED) // 用于接收帧数据的队列
    private val frameRate = 30 // 帧率为 20 fps

    fun startDecoding(width: Int, height: Int) {
        if (isDecoding) return

        val mediaFormat = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_HEVC, width, height).apply {
            setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface)
            setInteger(MediaFormat.KEY_BIT_RATE, width * height)
            setInteger(MediaFormat.KEY_FRAME_RATE, frameRate)
            setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1)
        }
        startTimeNanos = System.nanoTime() // 记录解码开始时间
        mediaCodec = MediaCodec.createDecoderByType(MediaFormat.MIMETYPE_VIDEO_HEVC)
        mediaCodec?.configure(mediaFormat, surface, null, 0)
        mediaCodec?.start()

        isDecoding = true
        decodeScope.launch { decodeLoop() }
    }

    private suspend fun decodeLoop() = withContext(Dispatchers.IO) {
        val bufferInfo = MediaCodec.BufferInfo()
        while (isDecoding) {
            val inputBufferIndex = mediaCodec?.dequeueInputBuffer(10000) ?: -1
            if (inputBufferIndex >= 0) {
                val inputBuffer = mediaCodec?.getInputBuffer(inputBufferIndex)
                // 从队列中获取帧数据
                val (frameData, presentationTimeUs) = frameDataQueue.receive()
                inputBuffer?.clear()
                inputBuffer?.put(frameData)
                // 根据帧计数和起始时间计算 presentationTimeUs
                val calculatedPresentationTimeUs = (frameCount * 1_000_000_000L / frameRate).toLong() // 假设 frameRate 是每秒帧数
                mediaCodec?.queueInputBuffer(inputBufferIndex, 0, frameData.limit(), calculatedPresentationTimeUs,0)
            }

            val outputBufferIndex = mediaCodec?.dequeueOutputBuffer(bufferInfo, 10000) ?: -1
            if (outputBufferIndex >= 0) {
                mediaCodec?.releaseOutputBuffer(outputBufferIndex, true)
            } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
                // 处理输出格式变化
            }
        }
    }

    fun decodeFrame(frameData: ByteBuffer) {
        if (!isDecoding) return
        decodeScope.launch {
            frameDataQueue.send(Pair(frameData, 0L))
        }
    }

    fun stopDecoding() {
        isDecoding = false
        decodeScope.cancel()
        mediaCodec?.stop()
        mediaCodec?.release()
        mediaCodec = null
    }
}